]> git.r.bdr.sh - rbdr/Flat-Bezel.qsplugin/blame - Flat Bezel/BBSearchObjectView.m
Improve drawing, add padding to bezel
[rbdr/Flat-Bezel.qsplugin] / Flat Bezel / BBSearchObjectView.m
CommitLineData
5200836d
RBR
1#import "BBSearchObjectView.h"
2
3@implementation BBSearchObjectView
4+ (Class)cellClass { return [BBObjectCell class]; }
5
6@end
7
8@implementation BBCollectingSearchObjectView
9+ (Class)cellClass { return [BBObjectCell class]; }
10
11- (void)drawRect:(NSRect)rect {
12 NSRect frame = [self frame];
13 NSInteger count = [collection count];
14 if (![self currentEditor] && count) {
15 frame.origin = NSZeroPoint;
16 [[self cell] drawWithFrame:frame inView:self];
17 NSInteger i;
18 CGFloat iconSize = collectionSpace?collectionSpace:16;
19 CGFloat opacity = collecting?1.0:0.75;
20 QSObject *object;
21 CGFloat totalWidth = iconSize + 2;
22 for (i = 0; i<count; i++) {
23 object = [collection objectAtIndex:i];
24 NSImage *icon = [object icon];
25 [icon setSize:QSSize16];
26 [icon drawInRect:NSMakeRect(frame.size.width-totalWidth*(count-i), frame.origin.y+2, iconSize, iconSize) fromRect:rectFromSize([icon size]) operation:NSCompositingOperationSourceOver fraction:opacity];
27 }
28 } else {
29 [super drawRect:rect];
30 }
31}
32
33- (NSRect)textEditorFrame {
34 NSRect titleFrame = [self frame];
35 NSRect editorFrame = NSInsetRect(titleFrame, 8, 8);
36 editorFrame.origin = NSMakePoint(8, 8);
37 editorFrame = NSIntegralRect(editorFrame);
38 return editorFrame;
39}
40
41
42@end
43
44@implementation BBObjectCell
45
46- (NSCellImagePosition)preferredImagePosition {
47 return NSImageAbove;
48}
49
50- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
51 BOOL isFirstResponder = [[controlView window] firstResponder] == controlView && ![controlView isKindOfClass:[NSTableView class]];
52 BOOL dropTarget = ([self isHighlighted] && ([self highlightsBy] & NSChangeBackgroundCellMask) && ![self isBezeled]);
53
54 NSColor *fillColor;
55 NSColor *strokeColor = [NSColor clearColor];
56
57 if (isFirstResponder) {
58 fillColor = [self highlightColor];
59 } else {
60 fillColor = [self backgroundColor];
61 }
62
63 if (dropTarget) {
64 fillColor = [NSColor colorWithRed:0.77 green:0.91 blue:0.96 alpha:1];
65 }
66
67 [fillColor setFill];
68 [strokeColor setStroke];
69
70 NSBezierPath *roundRect = [NSBezierPath bezierPath];
71 [roundRect appendBezierPathWithRoundedRectangle:cellFrame withRadius:cellRadiusFactor];
72 [roundRect fill];
73
74 [self drawInteriorWithFrame:[self drawingRectForBounds:cellFrame] inView:controlView];
75}
76
77- (NSRect)titleRectForBounds:(NSRect)theRect
78{
79 NSRect rect = theRect;
80 rect = NSOffsetRect(rect, 0, -4);
81 return [super titleRectForBounds: rect];
82}
83
84- (void)drawTextForObject:(QSObject *)drawObject withFrame:(NSRect)cellFrame inView:(NSView *)controlView {
85 if ([self imagePosition] == NSImageOnly) return;
86
87 NSString *abbrString = nil;
88 if ([controlView respondsToSelector:@selector(matchedString)])
89 abbrString = [(QSSearchObjectView *)controlView matchedString];
90
91 NSString *nameString = nil;
92 NSIndexSet *hitMask = nil;
93
94 id ranker = [drawObject ranker];
95 if (ranker && abbrString)
96 nameString = [ranker matchedStringForAbbreviation:abbrString hitmask:&hitMask inContext:nil];
97
98 if (!nameString)
99 nameString = [drawObject displayName];
100
101 BOOL rankedStringIsName = [nameString isEqualToString:[drawObject displayName]] || nameString == nil;
102 if (!nameString) {
103 // fall back to the identifier if no reasonable name can be found
104 nameString = [drawObject identifier];
105 }
106 if (!nameString) {
107 // Couldn't find anything sensible to use for the name, fallback to avoid a crash
108 nameString = @"Unknown";
109 }
110
111 BOOL useAlternateColor = [controlView isKindOfClass:[NSTableView class]] && [(NSTableView *)controlView isRowSelected:[(NSTableView *)controlView rowAtPoint:cellFrame.origin]];
112 NSColor *mainColor = (textColor ? textColor : (useAlternateColor ? [NSColor alternateSelectedControlTextColor] : [NSColor controlTextColor]));
113 NSColor *fadedColor = [mainColor colorWithAlphaComponent:0.50];
114 NSRect textDrawRect = [self titleRectForBounds:cellFrame];
115
116 NSMutableAttributedString *titleString = [[[NSMutableAttributedString alloc] initWithString:nameString] autorelease];
117 [titleString setAttributes:rankedStringIsName ? nameAttributes : detailsAttributes range:NSMakeRange(0, [titleString length])];
118
119 // Bring out the matched letters
120 if (abbrString && ![abbrString hasPrefix:@"QSActionMnemonic"]) {
121 [titleString addAttribute:NSForegroundColorAttributeName value:rankedStringIsName ? fadedColor : [fadedColor colorWithAlphaComponent:0.8] range:NSMakeRange(0, [titleString length])];
122
123 NSUInteger i = 0;
124 NSUInteger j = 0;
125 NSUInteger hits[[titleString length]];
126 NSUInteger count = [hitMask getIndexes:(NSUInteger *)&hits maxCount:[titleString length] inIndexRange:nil];
127 NSDictionary *attributes = @{
128 NSForegroundColorAttributeName: rankedStringIsName ? mainColor : fadedColor
129 };
130 for(i = 0; i<count; i += j) {
131 for (j = 1; i+j<count && hits[i+j-1] +1 == hits[i+j]; j++);
132 [titleString addAttributes:attributes range:NSMakeRange(hits[i], j)];
133 }
134 } else {
135 [titleString addAttribute:NSBaselineOffsetAttributeName value:[NSNumber numberWithDouble:-1.0] range:NSMakeRange(0, [titleString length])];
136 }
137//
138// // Ranked string and nameString aren't the same. Show 'nameString ⟷ rankedString' in the UI
139// if (!rankedStringIsName && [drawObject displayName].length) {
140// [titleString addAttribute:NSFontAttributeName value:detailsFont range:NSMakeRange(0,[titleString length])];
141// NSMutableAttributedString *attributedNameString = [[NSMutableAttributedString alloc] initWithString:[drawObject displayName]];
142// [attributedNameString setAttributes:nameAttributes range:NSMakeRange(0, [[drawObject displayName] length])];
143//
144// [attributedNameString appendAttributedString:[[[NSAttributedString alloc] initWithString:@" ⟷ " attributes:rankedNameAttributes] autorelease]];
145// // the replaceCharacters... method inserts the new string into the receiver at the start of the work (range.location and range.length are 0)
146// [titleString replaceCharactersInRange:NSMakeRange(0,0) withAttributedString:attributedNameString];
147// [attributedNameString release];
148// }
149
150 if (showDetails) {
151 NSString *detailsString = [drawObject details];
152
153 NSRange returnRange = [detailsString rangeOfString:@"\n"];
154 if (returnRange.location != NSNotFound) {
155 detailsString = [detailsString substringToIndex:returnRange.location];
156 }
157
158 detailsAttributes = [detailsAttributes mutableCopy];
159 [detailsAttributes setValue:[NSColor grayColor] forKey:NSForegroundColorAttributeName];
160
161 if (detailsString && detailsString.length && ![detailsString isEqualToString:nameString]) {
162 [titleString appendAttributedString:[[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"\n%@",detailsString] attributes:detailsAttributes] autorelease]];
163 }
164 }
165
166 NSRect centerRect = rectFromSize([titleString size]);
167 centerRect.size.width = NSWidth(textDrawRect);
168 centerRect.size.height = MIN(NSHeight(textDrawRect), centerRect.size.height);
169 [titleString drawInRect:centerRectInRect(centerRect, textDrawRect)];
170}
171
953623b9
RBR
172- (void)drawSearchPlaceholderWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
173 NSString *defaultText = NSLocalizedStringWithDefaultValue(@"Type to search", nil, [NSBundle mainBundle], @"Type to search", @"Hint that appears in the first pane of the QS interface when it's empty.");
174 NSSize textSize = [defaultText sizeWithAttributes:nameAttributes];
175 NSRect textRect = centerRectInRect(rectFromSize(textSize), cellFrame);
176 BOOL isFirstResponder = [[controlView window] firstResponder] == controlView && ![controlView isKindOfClass:[NSTableView class]];
177
178 if (isFirstResponder && [controlView isKindOfClass:[QSSearchObjectView class]]) {
179 NSImage *find = [NSImage imageWithSystemSymbolName:@"magnifyingglass.circle.fill" accessibilityDescription:nil];
180
181
182 [find setSize:QSSize16];
183 NSRect findImageRect = expelRectFromRectOnEdge(centerRectInRect(rectFromSize([find size]), cellFrame), textRect, NSRectEdgeMinX, -2);
184
185
186 NSGraphicsContext *graphicsContext = [NSGraphicsContext currentContext];
187 [graphicsContext saveGraphicsState];
188 CGContextRef context = [graphicsContext CGContext];
189 CGContextBeginTransparencyLayerWithRect(context, findImageRect, nil);
190 CGContextSetBlendMode(context, kCGBlendModeNormal);
191 [find drawInRect:findImageRect fromRect:rectFromSize([find size]) operation:NSCompositingOperationSourceOver fraction:1];
192 CGContextSetBlendMode(context, kCGBlendModeSourceIn);
193 CGContextSetFillColorWithColor(context, [[NSColor textColor] CGColor]);
194 CGContextFillRect(context, findImageRect);
195 CGContextEndTransparencyLayer(context);
196
197 [defaultText drawInRect:textRect withAttributes:nameAttributes];
198 }
199}
5200836d 200
953623b9 201@end